#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>

#include "../logServer/clogger.h"
#include "wcdmaApi.h"
#include "wcdmaMsgHandle.h"
#include "common.h"

#define WCDMALogDebug(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_DEBUG, fmt, ##args);
#define WCDMALogInfo(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_INFO, fmt, ##args);
#define WCDMALogNotice(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_NOTICE, fmt, ##args);
#define WCDMALogWarning(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_WARNING, fmt, ##args);
#define WCDMALogError(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_ERR, fmt, ##args);
#define WCDMALogCrit(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_CRIT, fmt, ##args);
#define WCDMALogAlert(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_ALERT, fmt, ##args);
#define WCDMALogEmerg(fmt, args...) CLogger(MODULE_WCDMA_CAP, __FILE__, __LINE__, LOG_EMERG, fmt, ##args);

#define WCDMA_DEBUG  1
#define WCDMA_SLOT   11

using namespace std;

//communication address
sockaddr_in 	   wcdmaRemoteAddr;
sockaddr_in 	   wcdmaLocalAddr;
conn_context       wcdma_udp_ctxt;
conn_t*            wcdma_udp_conn_t = NULL;

//wcdma module state
const char *wcdmaStatesStr[(int)WCDMA_MODULE_NSYNC+1] =
{
    "Idle",
    "Preconfig",
    "Configuring",
    "Configured",
    "Restarting",
    "Running",
    "Shutdown",
    "OOS"
};

//some runtime information
wcdmaParam_t                gWcdmaParam;                    /* global wcdma configuration */
wcdmaModuleState_t          gWcdmaState;                    /* global wcdma module state */
tlvCmdRecord_t				wcdmaCmdRecord[2];		            /* save destination module ID and cmd code */
time_t						wdmaCurTime;		            /* current time counter since from 1970 */
U8							wcdmaBackedMsg[256];		    /* the lastest udp message */
U16                         wcdmaBackedMsgLen;              /* backed message length */
U32                         wcdmaSendcout[RC_MOD_INVALID];  /* send ok */   
U16 						wcdmaHbCounter;		            /* count how many heart beat message received */
U16                         wcdmaResetCount;
bool                        wcdmaIsSetTime = false;          /* set wcdma board time at the first time */
pthread_mutex_t             wcdmaMutex;                     /* for modify cdma baseband state between two thread */

MODREG modWcdmaInfo = {MODULE_WCDMA_CAP, true, true, TICK_INTERVAL, (char *)"WCDMA"};
static bool wcdmaHavedRecvImsi = false;
#define WCDMA_MODULE_HEARTBEAT_INTERVAL        5000
#define WCDMA_BOARD_HEARTBEAT_CHECK            2 * 60 * 1000  
//const U32 checkWcdmaImsiInterval = 120 * 60 * 1000; //2 hours
const U32 checkWcdmaImsiInterval = 10 * 60 * 1000; //2 //10min

void* pWcdmaBoardHeartBeatTimer = NULL;
void* pWcdmaModuleHeartBeatTimer = NULL;
void* pWcdmaRestartCommandTimer = NULL;
void* pWcdmaRecvImsiTimer = NULL;
void* pWaitMsgResponseTimer = NULL; //for carrier 0

//module init function
bool wcdmaModuleInit();
void wcdma_tlv_msg_handler();
bool initWcdmaInternalMsgTask();
bool initWcdmaUdpMsgTask();

/*************************************************************************/
/*     handle PA control */
/**********************************************************************/
static bool wcdmaPaIsOn = false;
static bool wcdmaPaSettingOn = false;
static int wcdmaMaxPaCtrlTm = 3;
static U8 wcdmaPaHandleType = 0;
static bool wcdmaPaState = false;
static bool wcdmaIsReboot = true;

#define WCDMA_PA_TYPE_REBOOT          1
#define WCDMA_PA_TYPE_NOTHING         0
#define WCDMA_PA_TYPE_RESTART         2

const U32 contrlWcdmaPaTimeOut = 30* 1000;
void* pWcdmaCtrlPaTimer = NULL;
void handleWcdmaCtrlPaTimer(void *h);
void handleWcdmaPaCtrl(bool settingOn, U8 type);


/*
 *******************************************************************************
 *            common function definition
 *
 ******************************************************************************* 
 */
PCMDHEADER getWcdmaTlvCmdHeader(U16 cmdType);
U16 getWcdmaTlvSrcID(U16 cmdType);
void saveWcdmaMsgCmdCodeAndSrcID(U16 srcID, PCMDHEADER);
void setwcdmadevtimestr(char * str);
void backupWcdmaLatestUdpMsg(const char *msg, U16 msglen);
void resendingWcdmaLatestUdpMsg();
void send_wcdma_udp_msg(const char *msg, U16 length);
bool init_wcdma_udp_context(sockaddr_in *remote_addr, sockaddr_in* local_addr);
wcdmaModuleState_t getWcdmaModuleState();
void setWcdmaModuleState(wcdmaModuleState_t state);
void setWcdmaModuleRecvImsi();
bool getWcdmaModuleRecvImsi();
/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @param   result            -  failed or success
 * @return  true or false
 ****************************************************************************************
 */
bool buildAndSendTlvCmdSetResponseMsg(U8 cmdType, U32 result, U32 paraType, U32 paraValue);

/*
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @return  none
 ****************************************************************************************
*/
void buildAndSendTlvEventNoParam(U16 moduleID, U16 cmdCode);

/*
 ****************************************************************************************
 * @brief   build and report wcdma module status
 * @return  none
 ****************************************************************************************
*/
void handleWcdmaTlvTimeTick();
void handleWcdmaTlvCmdMsg(U8 *payload);
void handleWcdmaTlvCmdSetMsg(U8 *payload);
void handleWcdmaTlvCmdSetRspMsg(void *payload);

void handleWcdmaTlvConfigSetTime(PCMDHEADER pCmd);
void handleWcdmaGetWcdmaConfiguration(PCMDHEADER pCmd);
void handleWcdmaTlvCmdGetMsg(U8 *payload);
void handleWcdmaTlvCmdEventMsg(U8 *payload);
void handleWcdmaTlvCtrlRestartMsg();
void handleWcdmaTlvCtrlWirelessOffMsg(PCMDHEADER pCmd);
void handleWcdmaTlvCtrlWirelessOnMsg(PCMDHEADER pCmd);
void handleWcdmaHeartBeatTimer(void *h);
void handleWcdmaTlvSetTxAttuation(PCMDHEADER pCmd);
void handleWcdmaTlvConfigWirelessMsg(PCMDHEADER pCmd);
void handleWcdmaRecvImsiTimer(void *h);
void handleWcdmaModuleHeartBeatTimer(void *h);
void handleWcdmaBoardHeartBeatTimer(void *h);
void buildAndReportWcdmaModuleStatus();
void reportHeartBeatWcdmaModuleStatus();

/**
 ****************************************************************************************
 * @brief   build and report wcdma configuration 
 * @return  none
 ****************************************************************************************
*/
void buildAndReportWcdmaConfiguration(PCMDHEADER pCmd);
void buildAndReportStateInfo(U16 cmdCode);

/*
 *******************************************************************************
 *            udp relate function
 *
 ******************************************************************************* 
*/
void handleWcdmaUdpBsConfigPowerResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsConfigParamResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsConfigStatusResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsConfigIpResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsConfigRestartResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsUploadIMSI(const char* buf, ssize_t len);

void handleWcdmaConfigTimeResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsConfig(const char* buf, ssize_t len);
void handleWcdmaUdpBsSettingPilotResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsSettingAutoLacResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsSettingSwVersionResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsSettingGetDacResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsSettingSetDacResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsSetting(const char* buf, ssize_t len);

void handleWcdmaUdpRadioOutputStartResponse(const char* buf, ssize_t len);
void handleWcdmaUdpRadioOutputStopResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsRadioOutput(const char* buf, ssize_t len);

void handleWcdmaUdpBsParamReport(const char* buf, ssize_t len);
void handleWcdmaUdpBsParamResponse(const char* buf, ssize_t len);
void handleWcdmaUdpBsParam(const char* buf, ssize_t len);

/*
 *******************************************************************************
 *            common function definition
 *
 ******************************************************************************* 
 */
void insplit(std::string& s, const std::string& delim, std::vector<std::string> *ret)
{
    unsigned last = 0;
    unsigned index = s.find_first_of(delim, last);
    while(index != std::string::npos)
    {
        ret->push_back(s.substr(last,index-last));
        last = index+1;
        index = s.find_first_of(delim,last);
    }

    if(index-last > 0)
    {
        ret->push_back(s.substr(last,index-last));
    }
}

inline time_t getWcdmaCurrentTime()
{
    return wdmaCurTime;
}

inline void setWcdmaCurrentTime()
{
    wdmaCurTime = time(NULL);
}

inline void increaseWcdmaCurrentTime(int tick)
{
    wdmaCurTime += tick;
}

inline void increaseWcdmaSendCounter(RESULT rc)
{
    wcdmaSendcout[rc]++;
}

U16 getWcdmaTlvSrcID(U16 cmdType)
{
     return wcdmaCmdRecord[cmdType].srcID;
}

PCMDHEADER getWcdmaTlvCmdHeader(U16 cmdType)
{
    return &(wcdmaCmdRecord[cmdType].cmdHdr);
}

void saveWcdmaMsgCmdCodeAndSrcID(U16 srcID, PCMDHEADER hdr)
{
     wcdmaCmdRecord[hdr->cmdType].srcID = srcID;
     wcdmaCmdRecord[hdr->cmdType].cmdHdr.cmdIndex = hdr->cmdIndex;
     wcdmaCmdRecord[hdr->cmdType].cmdHdr.cmdCode = hdr->cmdCode;
     wcdmaCmdRecord[hdr->cmdType].cmdHdr.cmdType = hdr->cmdType;

     WCDMALogDebug("modId[0x%x] cmdcode = %02x, srcId = %02x ", MODULE_WCDMA_CAP, hdr->cmdCode, srcID);
}

static void closeWcdmaSession(void)
{    
	WCDMALogNotice("System is exiting, closing wcdma socket.");
	release_connection(wcdma_udp_conn_t);
}
/**
 **************************************************************************
 * handle PA
 *
 *****************************************************************************/
void buildAndSendWcdmaPaCtrlCommand(bool isOn)
{
    U8 slotId = 6;
    if (isOn)
    {
        CM_SendMsg_1Para(MODULE_PA, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PA_SWITCH_ON, 0,
                PARA_TYPE_PA_ADDR, sizeof(U8), &slotId);
    }
    else
    {
        CM_SendMsg_1Para(MODULE_PA, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PA_SWITCH_OFF, 0,
                PARA_TYPE_PA_ADDR, sizeof(U8), &slotId);		
    }
}

void handleWcdmaCtrlPaTimer(void *h)
{
    if (wcdmaMaxPaCtrlTm <= 0)
    {

        WCDMALogWarning("wcdma pa control max time reach ");
        if (wcdmaPaHandleType == WCDMA_PA_TYPE_NOTHING)
        {
            WCDMALogNotice("wcdma pa contorl failed  do nothing");
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_REBOOT)
        {
            WCDMALogNotice("wcdma pa contorl failed reboot");
            handleWcdmaTlvCtrlRestartMsg();
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_RESTART)
        {
            WCDMALogNotice("wcdma pa contorl failed restart");
            U8 slotId = 8;
            CM_SendMsg_1Para(MODULE_PM, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            wcdmaResetCount++;
        }

        return;

    }
    wcdmaMaxPaCtrlTm--;
    if (wcdmaPaIsOn == wcdmaPaSettingOn)
    {
        WCDMALogNotice("wcdma pa state is same  do nothing");
        return;
    }

    buildAndSendWcdmaPaCtrlCommand(wcdmaPaSettingOn);
    MOD_timerRestart(pWcdmaCtrlPaTimer, contrlWcdmaPaTimeOut);
}


void handleWcdmaCtrlPaResult(bool isOn)
{
    if (!isOn && wcdmaPaSettingOn)
    {
        WCDMALogWarning("wcdma pa handle type is chang so do default command");
        handleWcdmaTlvCtrlRestartMsg();
    }


    if (isOn == wcdmaPaSettingOn)
    {
        wcdmaPaIsOn = isOn;
        WCDMALogWarning("wcdma pa control  success");
        if (wcdmaPaHandleType == WCDMA_PA_TYPE_NOTHING)
        {
            WCDMALogNotice("wcdma pa control	success  do nothing");
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_REBOOT)
        {
            WCDMALogNotice("wcdma pa control	success reboot");
            handleWcdmaTlvCtrlRestartMsg();
			wcdmaPaState = false;
			wcdmaIsReboot = true;
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_RESTART)
        {
            WCDMALogNotice("wcdma pa control	success so restart");
            U8 slotId = 8;
            CM_SendMsg_1Para(MODULE_PM, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            wcdmaResetCount++;
			wcdmaPaState = false;
			wcdmaIsReboot = true;

        }
        ///MOD_timerClear(MODULE_GSM_CAP, pGsmCtrlPaTimer);
    }
    else
    {
        WCDMALogWarning("wcdma pa handle type is chang");
    }	

}
void handleWcdmaPaCtrl(bool settingOn, U8 type)
{
    wcdmaPaHandleType = type;
    if ((wcdmaPaIsOn == settingOn) && (wcdmaPaSettingOn == settingOn))
    {
        if (wcdmaPaHandleType == WCDMA_PA_TYPE_NOTHING)
        {
            WCDMALogNotice("wcdma pa state is same  do nothing");
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_REBOOT)
        {
            WCDMALogNotice("wcdma pa state is same reboot");
            handleWcdmaTlvCtrlRestartMsg();
        }
        else if (wcdmaPaHandleType == WCDMA_PA_TYPE_RESTART)
        {
            WCDMALogNotice("wcdma pa state is same restart");

            WCDMALogWarning("reboot wcdma baseband time is %d ",	wcdmaResetCount);
            U8 slotId = 8;
            CM_SendMsg_1Para(MODULE_PM, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_SET, CMD_CODE_PM_RESTART, 0,
                    PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), &slotId);
            wcdmaResetCount++;
        }

        return;
    }

    wcdmaMaxPaCtrlTm = 2;
    wcdmaPaSettingOn = settingOn;
    buildAndSendWcdmaPaCtrlCommand(wcdmaPaSettingOn);
    if (pWcdmaCtrlPaTimer == NULL)
    {
        pWcdmaCtrlPaTimer = MOD_timerStart(MODULE_WCDMA_CAP, contrlWcdmaPaTimeOut, handleWcdmaCtrlPaTimer, NULL);
    }
    else
    {

        MOD_timerRestart(pWcdmaCtrlPaTimer, contrlWcdmaPaTimeOut);
    }


}


/************************************************/
/* pa											*/
/************************************************/
void handleWcdmaPAOnReponse(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32  result = PARA_VALUE_ERROR_GENERAL_ERROR;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)	  
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                result = *((U32 *) paraValue);

                break;

            case PARA_TYPE_PA_ADDR:

                break;
            default:
                WCDMALogError("Unknown paramType error in received cmdcode = %x", pCmd->cmdCode);


                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        WCDMALogError("wcdma pa reponse un pack failed");
        return;
    }

    if (result == PARA_VALUE_ERROR_NO_ERROR)
    {
        handleWcdmaCtrlPaResult(true);

    }

}

void handleWcdmaPAOffReponse(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32  result = PARA_VALUE_ERROR_GENERAL_ERROR;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)	  
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                result = *((U32 *) paraValue);

                break;

            case PARA_TYPE_PA_ADDR:

                break;
            default:
                WCDMALogError("Unknown paramType error in received cmdcode = %x", pCmd->cmdCode);


                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        WCDMALogError("wcdma pa reponse un pack failed");
        return;
    }

    if (result == PARA_VALUE_ERROR_NO_ERROR)
    {
        handleWcdmaCtrlPaResult(false);

    }

}


void handleWcdmaTlvCmdSetRspMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {	
        case CMD_CODE_PA_SWITCH_ON:
            handleWcdmaPAOnReponse(pCmd);
            break;
        case CMD_CODE_PA_SWITCH_OFF:
            handleWcdmaPAOffReponse(pCmd);
            break;

        default:
            WCDMALogWarning("Unknown cmdCode = %x ",  pCmd->cmdCode);
            break;
    }	
}


/**
 ****************************************************************************************
 * Set devtimestr, time is string 
 *   
 ****************************************************************************************
 */ 
void setwcdmadevtimestr(char *str)
{
    time_t   now;
    struct   tm  *timenow;

    /* 1. get system time */
    now = getWcdmaCurrentTime();
    timenow = localtime(&now);
    char s[15];
    strftime(s, sizeof(s), "%Y%m%d%H%M%S", timenow);
    WCDMALogDebug( "time:%s", s);
    memcpy(str, s, sizeof(s));
    WCDMALogDebug( "DEVTIMESTR:%s",str);
}

void wcdma_tlv_msg_handler()
{
    MSGHEADER msgHdr;
    U8 payload[MAX_MSG_SIZE];
    PCMDHEADER pCmd;
	  
    while(1)
    {
        if( MSG_read(MODULE_WCDMA_CAP, &msgHdr, (void *)payload) != 0 )
        {
            //dbgprintf(DEBUG_ERROR, stderr, "internal_msg_thread:MSG_read error. \n");
            continue;
        }
    
        if( MODULE_WCDMA_CAP != msgHdr.dstID )
        {
            WCDMALogError("received a wrong tlv msg id = %d ", msgHdr.dstID);
            continue;
        }
        
        WCDMALogDebug("received tlv msg id = %d ", msgHdr.srcID);
        switch ( msgHdr.msgType )
        {
            case MSG_TYPE_COMMAND:
            	pCmd = (PCMDHEADER )payload;
            	
            	//save cmdcode and srcId for response
                if (pCmd->cmdType == CMD_SET || pCmd->cmdType == CMD_GET)
            	    saveWcdmaMsgCmdCodeAndSrcID(msgHdr.srcID, pCmd);            	
            	handleWcdmaTlvCmdMsg(payload);
            	break;
            case MSG_TYPE_TICK:
            	handleWcdmaTlvTimeTick();
            	break;
            default:
                WCDMALogError("Unknown msg type %x.", msgHdr.msgType);
                break;
        }
    }
}

bool wcdmaModuleInit()
{
    //1. init global parameter
    memset(&gWcdmaParam, 0x0, sizeof(wcdmaParam_t));
    memset(&wcdmaCmdRecord, 0x0, sizeof(tlvCmdRecord_t) * 2);
    wcdmaCmdRecord[0].cmdHdr.cmdCode = INVALID_CMD_CODE;
    wcdmaCmdRecord[1].cmdHdr.cmdCode = INVALID_CMD_CODE;

    memset(wcdmaBackedMsg, 0x0, 256);
	wcdmaBackedMsgLen = 0;
	gWcdmaState = WCDMA_MODULE_IDLE;
	wcdmaHbCounter = 0;
    wcdmaResetCount = 0;
    //2. register module
    if( RC_OK != MOD_register(&modWcdmaInfo) )
    {
        WCDMALogError("can't register wcdma module with syscore\n", MODULE_WCDMA_CAP);
        return false;
    }

    //3. init udp context
    wcdmaRemoteAddr.sin_addr.s_addr = inet_addr(WCDMA_BOARD_IP);
	wcdmaRemoteAddr.sin_port = htons(atoi(WCDMA_BOARD_UDP_PORT));
    wcdmaRemoteAddr.sin_family = AF_INET;
    wcdmaLocalAddr.sin_addr.s_addr = inet_addr(WCDMA_MODULE_IP);
	wcdmaLocalAddr.sin_port = htons(atoi(WCDMA_MODULE_UDP_PORT));
    wcdmaLocalAddr.sin_family = AF_INET;
    if(!init_wcdma_udp_context(&wcdmaRemoteAddr, &wcdmaLocalAddr) )
    {
        WCDMALogError("init udp connection context.\n", MODULE_WCDMA_CAP);
        return false;
    }

    //set system time
    setWcdmaCurrentTime();

    return true;
}

//
RESULT WCDMA_init(void)
{
    //1. wcdma module initialization
    if( !wcdmaModuleInit() )
    {	
        WCDMALogError("WCDMA module initialization failed.");
    	return RC_FAIL; 
    }
    
    //2. create udp msg handler thread 
    if( !initWcdmaUdpMsgTask() )
    {
        WCDMALogError("Can't create wcdmaUdpMsgTask thread.");
    	return RC_FAIL;
    }

    //3. create internal msg handler thread 
    if( !initWcdmaInternalMsgTask() )
    {
        WCDMALogError("Can't create wcdmaInternalMsgtask thread.");
    	return RC_FAIL;
    }

    return RC_OK;
}

static void* wcdma_internal_task_thread(void *arg __attribute__((unused)))
{
    pthread_setname_np(pthread_self(), "wcdma_internal");
    pWcdmaModuleHeartBeatTimer = MOD_timerStart(MODULE_WCDMA_CAP, WCDMA_MODULE_HEARTBEAT_INTERVAL, handleWcdmaModuleHeartBeatTimer, NULL);
    pWcdmaBoardHeartBeatTimer = MOD_timerStart(MODULE_WCDMA_CAP, WCDMA_BOARD_HEARTBEAT_CHECK, handleWcdmaBoardHeartBeatTimer, NULL);
    pWcdmaRecvImsiTimer = MOD_timerStart(MODULE_WCDMA_CAP, checkWcdmaImsiInterval, handleWcdmaRecvImsiTimer, NULL);
	atexit(closeWcdmaSession);
	//start to handle message from other module
    wcdma_tlv_msg_handler();

    WCDMALogNotice("Exiting the wcdma_internal_task_thread thread.");
    pthread_exit( (void*)0 );
}

bool initWcdmaInternalMsgTask()
{
    pthread_t       thread;

    if(pthread_create(&thread, NULL, wcdma_internal_task_thread, NULL) != RC_OK)
    {
        return false;
    }

    return true;
}



/****************************************************************************************/
/*           tlv relate function                                                        */
/****************************************************************************************/
/****************************************************************************************/
/*           Handle time tick from dispatcher module                                    */
/****************************************************************************************/
void handleWcdmaTlvTimeTick()
{
    increaseWcdmaCurrentTime(TICK_SECOND);
    MOD_timerProc(MODULE_WCDMA_CAP);
} 

void handleWcdmaModuleHeartBeatTimer(void *h)
{
    U32 rc = PARA_VALUE_SYSMONITOR_MODULE_OK;
    CM_SendMsg_1Para(MODULE_SYSMONITOR, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_EVENT, CMD_CODE_SYSMONITOR_HEARTBEAT, 0,
        PARA_TYPE_SYSMONITOR_MODULE_STATE,sizeof(U32), (U8*)&rc);   
     
    MOD_timerRestart(pWcdmaModuleHeartBeatTimer, WCDMA_MODULE_HEARTBEAT_INTERVAL);
}

void handleWcdmaBoardHeartBeatTimer(void *h)
{
    MOD_timerRestart(pWcdmaBoardHeartBeatTimer, WCDMA_BOARD_HEARTBEAT_CHECK);
    
    if(WCDMA_MODULE_IDLE == getWcdmaModuleState() || 
       WCDMA_MODULE_CONFIGING == getWcdmaModuleState() )
    {
        return;
    }

    if (WCDMA_MODULE_NSYNC == getWcdmaModuleState() && wcdmaResetCount >= 3)
    {
        WCDMALogNotice("wcdma reset times is %d ", wcdmaResetCount);
        if (wcdmaResetCount == 3)
        {
            wcdmaResetCount++;
            buildAndSendTlvEventNoParam(MODULE_INTF, CMD_WCDMA_EVT_LOST);
            saveImportantLog((char *)"wcdma baseband lost connction, hard reset no use");
        }
        return;
    }
    

    //wcdma board is sync with x86
    if (wcdmaHbCounter > 0)
    {
        wcdmaHbCounter = 0;
        wcdmaResetCount = 0;
    }
    else
    {
        //if wcdma board is out of sync, whether need trigger an alert and reboot?	  	  	  
        setWcdmaModuleState(WCDMA_MODULE_NSYNC);
       
        //sent to power module to restart wcdma board
		//handleTlvCtrlResetMsg(0);
        buildAndSendTlvEventNoParam(MODULE_INTF, CMD_WCDMA_EVT_NSYNC);
        handleWcdmaPaCtrl(false, WCDMA_PA_TYPE_RESTART);
        WCDMALogWarning("reboot wcdma baseband time is %d", wcdmaResetCount);
    }
}
 
void handleWcdmaRecvImsiTimer(void *h)
{
    MOD_timerRestart(pWcdmaRecvImsiTimer, checkWcdmaImsiInterval);
    
    if(WCDMA_MODULE_IDLE == getWcdmaModuleState() || 
       WCDMA_MODULE_CONFIGING == getWcdmaModuleState() || 
       WCDMA_MODULE_NSYNC == getWcdmaModuleState() )
    {
        return;
    }
    if (!getWcdmaModuleRecvImsi())
    {
        buildAndSendTlvEventNoParam(MODULE_INTF, CMD_WCDMA_EVT_NOT_RECV_IMSI);  
		handleWcdmaPaCtrl(false, WCDMA_PA_TYPE_RESTART);

        setWcdmaModuleState(WCDMA_MODULE_NSYNC);
        WCDMALogWarning("wcdma module can not recv imsi in two hour");    
        return;  
    }
    WCDMALogInfo("wcdma module have recv imsi in two hour");   

}

void handleWcdmaTlvCmdMsg(U8 *payload)
{
    PCMDHEADER pCmd = (PCMDHEADER) payload;

    switch (pCmd->cmdType)
    {
        case CMD_SET:
       	    handleWcdmaTlvCmdSetMsg(payload);
            break;
        case CMD_GET:
            handleWcdmaTlvCmdGetMsg(payload);
            break;
        case CMD_EVENT:
            handleWcdmaTlvCmdEventMsg(payload);
            break;

		case CMD_SET_RESPONSE:
			handleWcdmaTlvCmdSetRspMsg(payload);
			break;
			
        default:
            WCDMALogWarning("Unknown CmdType = %x.",  pCmd->cmdType);
            break;
    }
}

void handleWcdmaTlvCmdSetMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;
	 
    switch (pCmd->cmdCode)
    {
        case CMD_WCDMA_RESTART:
            handleWcdmaPaCtrl(false, WCDMA_PA_TYPE_REBOOT);
            break;
        case CMD_WCDMA_WIRELESS_OFF:
            handleWcdmaTlvCtrlWirelessOffMsg(pCmd);
            break;
        case CMD_WCDMA_WIRELESS_ON:
            handleWcdmaTlvCtrlWirelessOnMsg(pCmd);
            break;    	
        case CMD_WCDMA_CFG_WIRELESS:
            handleWcdmaTlvConfigWirelessMsg(pCmd);
            break;
        case CMD_WCDMA_SET_TIME:
            handleWcdmaTlvConfigSetTime(pCmd);
            break;
        case CMD_WCDMA_TX_ATTUATION:
            handleWcdmaTlvSetTxAttuation(pCmd);
            break;
        default:
            WCDMALogWarning("Unknown cmdCode = %x.", pCmd->cmdCode);
            break;
    }
}

void handleWcdmaTlvConfigSetTime(PCMDHEADER pCmd)
{
    char curr[15];
	std::string setTime = "";

	setwcdmadevtimestr(curr);
    setTime += WCDMA_MESSAGE_TYPE_BS_CONFIG;
    setTime += WCDMA_MESSAGE_CODE_BS_CONFIG_TIME;
    setTime.append(curr);

    send_wcdma_udp_msg(setTime.c_str(), setTime.length());
}

void handleWcdmaGetWcdmaConfiguration(PCMDHEADER pCmd)
{
    std::string msg = "";

	msg += WCDMA_MESSAGE_TYPE_BS_PARAM;
	msg += WCDMA_MESSAGE_CODE_BS_PARAM_REQUEST;
    send_wcdma_udp_msg(msg.c_str(), msg.length());
}

void handleWcdmaTlvCmdGetMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {  	
        case CMD_WCDMA_GET_MODULE_STATUS:
            buildAndReportWcdmaModuleStatus();
            break;
        case CMD_WCDMA_GET_MODULE_CFG:
			handleWcdmaGetWcdmaConfiguration(pCmd);
            break; 
        case CMD_WCDMA_GET_WIRELESS_STATE:
            buildAndReportStateInfo(pCmd->cmdCode);
            break;
        default:
          WCDMALogWarning("Unknown cmdCode = %x.", pCmd->cmdCode);
          break;
    }		
}

void handleWcdmaTlvCmdEventMsg(U8 *payload)
{
    PCMDHEADER pCmd  = (PCMDHEADER ) payload;

    switch (pCmd->cmdCode)
    {  	
        case CMD_CODE_SYS_TIME_SYNC:
            setWcdmaCurrentTime();
            break;
        case CMD_CODE_SYS_WAKE:
            handleWcdmaTlvCtrlWirelessOnMsg(pCmd);
            break;
        case CMD_CODE_SYS_SLEEP:
            handleWcdmaTlvCtrlWirelessOffMsg(pCmd);
            break;
		case CMD_CODE_SYS_EXIT:	
            WCDMALogWarning("system is exiting, closing WCDMA socket.");
            release_connection(wcdma_udp_conn_t);
			break;
        default:
            WCDMALogWarning("Unknown cmdCode = %x.", pCmd->cmdCode);
            break;
    }	
}

void handleWcdmaTlvCtrlRestartMsg()
{
    std::string msg = "";

    if(getWcdmaModuleState() == WCDMA_MODULE_RUNNING)
    {
	    msg += WCDMA_MESSAGE_TYPE_BS_CONFIG;
	    msg	+= WCDMA_MESSAGE_CODE_BS_CONFIG_RESTART;
        send_wcdma_udp_msg(msg.c_str(), msg.length());
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_BASEBAND_INACTIVE);	
	}

}

void handleWcdmaTlvCtrlWirelessOffMsg(PCMDHEADER pCmd)
{
    std::string msg = "";
    if (getWcdmaModuleState() == WCDMA_MODULE_SHUTDOWN)
    {
        buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
        return;
    }
    if(getWcdmaModuleState() > WCDMA_MODULE_RESTART && getWcdmaModuleState() != WCDMA_MODULE_NSYNC)
    {
	    msg += WCDMA_MESSAGE_TYPE_RADIO_OUTPUT;
	    msg += WCDMA_MESSAGE_CODE_RADIO_OUTPUT_STOP;
        send_wcdma_udp_msg(msg.c_str(), msg.length());
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_BASEBAND_INACTIVE);	
	}
}

void handleWcdmaTlvCtrlWirelessOnMsg(PCMDHEADER pCmd)
{
    std::string msg = "";

    if(getWcdmaModuleState() > WCDMA_MODULE_RESTART && getWcdmaModuleState() != WCDMA_MODULE_NSYNC)
    {
	    msg += WCDMA_MESSAGE_TYPE_RADIO_OUTPUT ; 
	    msg += WCDMA_MESSAGE_CODE_RADIO_OUTPUT_START;
        send_wcdma_udp_msg(msg.c_str(), msg.length());
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_BASEBAND_INACTIVE);	
	}
}

void handleWcdmaTlvSetTxAttuation(PCMDHEADER pCmd)
{
    std::string msg = "";
    char att[2] = {0};
	
    PPARAM pParam =(PPARAM)(pCmd+1);

    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    bool rc = false;
    U8  attuation = 0;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TX_ATTUATION:
                attuation = *((U32 *) paraValue);
				sprintf(att, "%02d", attuation);

                break;
            default:
                WCDMALogError("Unknown paramType error in received cmdcode = %x.",   pCmd->cmdCode);

                rc = buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        WCDMALogError(" Parameter unpack error in received cmdcode = %x.", pCmd->cmdCode);

        if (!rc)  buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_ILLEGAL_PARA_STRUCT);
        
        return;
    }

	//itoa(attuation, att, 10);

	msg += WCDMA_MESSAGE_TYPE_BS_CONFIG;
	msg	+= WCDMA_MESSAGE_CODE_BS_CONFIG_POWER;

    //add space 
    msg += " ";
    //add power part
	msg += att;
	
    gWcdmaParam.txPower = attuation;	
    //send tx attuation to wcdma baseband
    send_wcdma_udp_msg(msg.c_str(), msg.length());

    //send success response
    buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
}

void handleWcdmaTlvConfigWirelessMsg(PCMDHEADER pCmd)
{
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    bool rc = false;
    bool isAutoLac = false;
	bool isDac = false;
	bool isTxPower = false;
		
	//for building message
    stringstream msgStream;
	
	wcdmaParam_t *pWcdmaParam = &gWcdmaParam;
	wcdmaParam_t tempParam;
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_WCDMA_WIRELESS_CONFIGURATION:
                memcpy(pWcdmaParam, paraValue, sizeof(wcdmaParam_t));
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_NODEB:
                memcpy(&tempParam, paraValue, sizeof(wcdmaParam_t));
                tempParam.autolac = pWcdmaParam->autolac;
				tempParam.dac = pWcdmaParam->dac;
				tempParam.txPower = pWcdmaParam->txPower;
                memcpy(pWcdmaParam, &tempParam, sizeof(wcdmaParam_t));
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_MCC:
                pWcdmaParam->mcc = *((U32 *) paraValue);
                break;	
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_LAC:	
                pWcdmaParam->lac = *((U32 *) paraValue);
                break;	
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_RAC:		
                pWcdmaParam->rac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_ARFCN:	
                pWcdmaParam->arfcn = *((U32 *) paraValue);
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_PSC:	
                pWcdmaParam->psc = *((U32 *) paraValue);
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_CELLID:	
                pWcdmaParam->psc = *((U32 *) paraValue);
                break;				
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_AUTOLAC:
				isAutoLac = true;
                pWcdmaParam->autolac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_DAC:
				isDac = true;
                pWcdmaParam->dac = *((U32 *) paraValue);
                break;
            case PARA_TYPE_WCDMA_WIRELESS_CONFIG_TXPOWER:
				isTxPower = true;
                pWcdmaParam->txPower = *((U32 *) paraValue);
                break;
            default:
                WCDMALogError("Unknown paramType error in received cmdcode = %x.",   pCmd->cmdCode);
                buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        WCDMALogError("Parameter unpack error in received cmdcode = %x", pCmd->cmdCode);

        buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_ILLEGAL_PARA_STRUCT);
        
        return;
    }

    if(isAutoLac)
    {
        if (pWcdmaParam->autolac >= 5 && pWcdmaParam->autolac <= 120)
        {
            msgStream << WCDMA_MESSAGE_TYPE_BS_SETTING; 
			msgStream << WCDMA_MESSAGE_CODE_BS_SETTING_AUTO_LAC;
			msgStream << pWcdmaParam->autolac;
        }
		else
		{
			WCDMALogError("Wrong AUTO LAC value cmdcode = %x.",	pCmd->cmdCode);		
			rc = buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_INVALID_PARAMETERS);
			return;
		}
    }
	else if(isDac)
	{
        if (pWcdmaParam->dac > 0 && pWcdmaParam->dac < 1024)
        {
            msgStream << WCDMA_MESSAGE_TYPE_BS_SETTING; 
			msgStream << WCDMA_MESSAGE_CODE_BS_SETTING_SET_DAC;
			msgStream << pWcdmaParam->dac;
        }
		else
		{
			WCDMALogError("Wrong DAC value cmdcode = %x.", pCmd->cmdCode);		
			rc = buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_INVALID_PARAMETERS);
			return;		
		}
	}
    else if(isTxPower)
    {
		if ( pWcdmaParam == NULL )
		{
			WCDMALogError("NULL while update total wcdma parameters cmdcode = %x.",	pCmd->cmdCode);		
			rc = buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_INVALID_PARAMETERS);
			return;
		}

		if(pWcdmaParam->txPower > 0)
		{
        	msgStream << WCDMA_MESSAGE_TYPE_BS_CONFIG; 
			msgStream << WCDMA_MESSAGE_CODE_BS_CONFIG_PARAM;		
		
			//set power
        	msgStream << WCDMA_MESSAGE_BODY_SETPOWER << WCDMA_MESSAGE_BODY_SPACE;
        	msgStream << setw(2) <<setfill('0') << pWcdmaParam->txPower;
		}
		else
		{
			WCDMALogNotice("Tx Power is too small.");		
		}

    }
    else
	{
		if ( pWcdmaParam == NULL )
		{
			WCDMALogError("NULL while update total wcdma parameters cmdcode = %x.",	pCmd->cmdCode);		
			rc = buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_INVALID_PARAMETERS);
			return;
		}
		
        msgStream << WCDMA_MESSAGE_TYPE_BS_CONFIG; 
		msgStream << WCDMA_MESSAGE_CODE_BS_CONFIG_PARAM;		
		
        //build the configuration message to wcdma board
        msgStream << WCDMA_MESSAGE_BODY_MCC << pWcdmaParam->mcc << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_MNC << setw(2) <<setfill('0') << pWcdmaParam->mnc << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_LAC << pWcdmaParam->lac << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_ARFCNo << pWcdmaParam->arfcn << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_PSC << pWcdmaParam->psc << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_RAC << pWcdmaParam->rac << WCDMA_MESSAGE_BODY_AT;
        msgStream << WCDMA_MESSAGE_BODY_CELLID << pWcdmaParam->cellid << WCDMA_MESSAGE_BODY_AT;
	}

	if(getWcdmaModuleState() != WCDMA_MODULE_IDLE)
	{
       send_wcdma_udp_msg(msgStream.str().c_str(),msgStream.str().length());
	}
	else
	{
       wcdmaIsSetTime = true;
	   setWcdmaModuleState(WCDMA_MODULE_CONFIGING);
	   WCDMALogNotice("wcdma board is not ready yet.");
	}

	buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
}

/**
 ****************************************************************************************
 * @brief   build and send cmd set response to dispatcher module, 
 * @param   result            -  failed or success
 * @return  none
 ****************************************************************************************
 */ 
bool buildAndSendTlvCmdSetResponseMsg(U8 cmdType, U32 result, U32 paraType, U32 paraValue)
{
    PCMDHEADER cmdHdr = getWcdmaTlvCmdHeader(cmdType);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
        //no need send reponse 
        WCDMALogNotice("no cmd code for cmdType = %x.", cmdType);
        return true;
    }

    U8 cmdResponse = (cmdType & 0xf) | 0x10;
   
    if(result == PARA_VALUE_RESULT_FAILED)
    {
        CM_SendMsg_2Para(getWcdmaTlvSrcID(cmdType), MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, cmdResponse, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result, paraType, 4, (U8 *)&paraValue);
    }
    else
    {
        CM_SendMsg_1Para(getWcdmaTlvSrcID(cmdType), MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, cmdResponse, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_RESULT, 4, (U8 *)&result);
    }

    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;

    return true;
}

/**
 ****************************************************************************************
 * @brief   build and send alarm to dispatcher module, 
 * @return  none
 ****************************************************************************************
 */
void buildAndSendTlvEventNoParam(U16 moduleID, U16 cmdCode)
{
    CM_SendMsg_noPara(moduleID, MODULE_WCDMA_CAP,MSG_TYPE_COMMAND, CMD_EVENT, cmdCode, 0);
	  	  	  
    return;
}

void reportHeartBeatWcdmaModuleStatus()
{
    wcdmaModuleState_t state = getWcdmaModuleState();
    
    U32 wirelessState = PARA_VALUE_WCDMA_WILELESS_OFF;

    if ( state == WCDMA_MODULE_RUNNING )
           wirelessState = PARA_VALUE_WCDMA_WILELESS_ON;

    CM_SendMsg_1Para(MODULE_SYSTEM, MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_EVENT, CMD_WCDMA_EVT_STATUS, 0,
                     PARA_TYPE_WCDMA_WILELESS_STATE, 4, (U8*)&wirelessState);
}

/**
 ****************************************************************************************
 * @brief   build and report wcdma module status, 
 * @return  none
 ****************************************************************************************
 */
void buildAndReportWcdmaModuleStatus()
{
    wcdmaModuleState_t state = getWcdmaModuleState();
    U32  msgLength = strlen(wcdmaStatesStr[state]);

    PCMDHEADER cmdHdr = getWcdmaTlvCmdHeader(CMD_GET);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
    	  //no need send reponse 
    	  return;
    }

    CM_SendMsg_1Para(getWcdmaTlvSrcID(CMD_GET), MODULE_WCDMA_CAP,MSG_TYPE_COMMAND, CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                     PARA_TYPE_WCDMA_MODULE_STATUS, msgLength, (U8 *)wcdmaStatesStr[state]);

    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;
}

void buildAndReportSendingCounter()
{
    U32 *pCounter = wcdmaSendcout;
    U32 msglen = sizeof(U32) * RC_MOD_INVALID;

    PCMDHEADER cmdHdr = getWcdmaTlvCmdHeader(CMD_GET);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
    	  //no need send reponse 
    	  return;
    }

    CM_SendMsg_1Para(getWcdmaTlvSrcID(CMD_GET), MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                     PARA_TYPE_WCDMA_SEND_COUNTER, msglen, (U8 *)pCounter);


    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;
}

void buildAndReportStateInfo(U16 cmdCode)
{
    wcdmaModuleState_t state = getWcdmaModuleState();
    
    PCMDHEADER cmdHdr = getWcdmaTlvCmdHeader(CMD_GET);

    if (cmdHdr->cmdCode == INVALID_CMD_CODE)
    {
    	  //no need send reponse 
    	  return;
    }

    if(CMD_WCDMA_GET_WIRELESS_STATE == cmdCode)
    {
        U32 wirelessState = PARA_VALUE_WCDMA_WILELESS_OFF;

        if ( state != WCDMA_MODULE_IDLE)
           wirelessState = PARA_VALUE_WCDMA_WILELESS_ON;

        CM_SendMsg_1Para(getWcdmaTlvSrcID(CMD_GET), MODULE_WCDMA_CAP, MSG_TYPE_COMMAND, CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                     CMD_WCDMA_GET_WIRELESS_STATE, 4, (U8 *)&wirelessState);
    }

    //reset the cmd set for next cmd message
    cmdHdr->cmdCode = INVALID_CMD_CODE;
}

/**
 ****************************************************************************************
 * @brief   build and report wcdma configuration 
 * @return  none
 ****************************************************************************************
 */
void buildAndReportWcdmaConfiguration(wcdmaParam_t *param)
{
    PCMDHEADER cmdHdr = getWcdmaTlvCmdHeader(CMD_GET);
    if(cmdHdr->cmdCode == CMD_WCDMA_GET_MODULE_CFG)
    {
        CM_SendMsg_1Para(getWcdmaTlvSrcID(CMD_GET), MODULE_WCDMA_CAP, MSG_TYPE_COMMAND,CMD_GET_RESPONSE, cmdHdr->cmdCode, cmdHdr->cmdIndex,
                         PARA_TYPE_WCDMA_WIRELESS_CONFIGURATION, sizeof(wcdmaParam_t), (U8 *)param);

		//reset the cmd set for next cmd message
		cmdHdr->cmdCode = INVALID_CMD_CODE;
    }
	else
	{
		WCDMALogWarning("configuration command was flushed by the following command");
		buildAndSendTlvCmdSetResponseMsg(CMD_GET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_UNKNOWN_PARATYPE);
	}
}

wcdmaModuleState_t getWcdmaModuleState()
{
    wcdmaModuleState_t state;

    pthread_mutex_lock(&wcdmaMutex);    
    state = gWcdmaState;
    pthread_mutex_unlock(&wcdmaMutex);

    WCDMALogDebug("Get WCDMA module state: %s.", wcdmaStatesStr[state]);

    return state;
}

void setWcdmaModuleState(wcdmaModuleState_t state)
{
    wcdmaModuleState_t laststate = gWcdmaState;
    pthread_mutex_lock(&wcdmaMutex);    
    gWcdmaState = state;
    pthread_mutex_unlock(&wcdmaMutex);
    if ((laststate != WCDMA_MODULE_RUNNING) && (state == WCDMA_MODULE_RUNNING) )
    {
        buildAndSendTlvEventNoParam(MODULE_INTF, CMD_WCDMA_EVT_SYNC);
        WCDMALogNotice("wcdma module is running");
    }
    WCDMALogDebug("Set WCDMA module state: %s", wcdmaStatesStr[state]);
}

void setWcdmaModuleRecvImsi()
{
    pthread_mutex_lock(&wcdmaMutex);    
    wcdmaHavedRecvImsi = true;
    pthread_mutex_unlock(&wcdmaMutex);
}

bool getWcdmaModuleRecvImsi()
{
    bool recv = false;
    pthread_mutex_lock(&wcdmaMutex);    
    recv = wcdmaHavedRecvImsi;
    wcdmaHavedRecvImsi = false;
    pthread_mutex_unlock(&wcdmaMutex);
    return recv;
}


/***************************************************************************************/
/* @brief   init udp connection context,                                               */ 
/* @param   msg         -  udp msg pointer                                             */ 
/* @param   length      -  udp msg length                                              */
/* @return  none                                                                       */ 
/***************************************************************************************/ 
void send_wcdma_udp_msg(const char *msg, U16 length)
{
    send_msg(wcdma_udp_conn_t, (const char*)msg, length);

	WCDMALogDebug("%s", msg); 

    //backup for re-sending because of no response or error occur 
    backupWcdmaLatestUdpMsg(msg, length);
}

/**
 ****************************************************************************************
 * @brief   resending latest backup udp message 
 * @param   msg         -  udp msg pointer
 * @param   length      -  udp msg length
 * @return  none
 ****************************************************************************************
 */ 
void resendingWcdmaLatestUdpMsg()
{
    send_wcdma_udp_msg((const char *)wcdmaBackedMsg, wcdmaBackedMsgLen);
}

/**
 ****************************************************************************************
 * @brief   backup latest udp message for re-sending, 
 * @param   msg         -  udp msg pointer
 * @param   length      -  udp msg length
 * @return  none
 ****************************************************************************************
 */ 
void backupWcdmaLatestUdpMsg(const char *msg, U16 msglen)
{
    memcpy(wcdmaBackedMsg, msg, msglen);    
    wcdmaBackedMsgLen= msglen;
}

/**
 ****************************************************************************************
 * Handle configuration type message response
 *
 ****************************************************************************************
 */ 
void handleWcdmaUdpBsConfigParamResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};
	wcdmaParam_t *param = &gWcdmaParam;

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {   
    	if (getWcdmaModuleState() != WCDMA_MODULE_RUNNING)
    	{
			setWcdmaModuleState(WCDMA_MODULE_RUNNING); 
			//handleWcdmaPaCtrl(true, WCDMA_PA_TYPE_NOTHING);
    	}
		   
	    WCDMALogNotice("NodeB configuration success.");  
    }
	else
	{
		WCDMALogError("NodeB configuration failure.");  	
	}

	if(param->txPower > 0)
	{
   	    stringstream msgStream;
        msgStream << WCDMA_MESSAGE_TYPE_BS_CONFIG; 
		msgStream << WCDMA_MESSAGE_CODE_BS_CONFIG_POWER;		
		
		//set power
        msgStream << WCDMA_MESSAGE_BODY_SETPOWER << WCDMA_MESSAGE_BODY_SPACE;
        msgStream << setw(2) <<setfill('0') << param->txPower;

		send_wcdma_udp_msg(msgStream.str().c_str(),msgStream.str().length());
	}
	
	if(param->autolac > 0)
	{
   	    stringstream msgStream;
        if (param->autolac >= 5 && param->autolac <= 120)
        {
            msgStream << WCDMA_MESSAGE_TYPE_BS_SETTING; 
			msgStream << WCDMA_MESSAGE_CODE_BS_SETTING_AUTO_LAC;
			msgStream << param->autolac;
		    send_wcdma_udp_msg(msgStream.str().c_str(),msgStream.str().length());		
        }		
	}

	if(param->rxPower > 0)
	{
   	    stringstream msgStream;
        if (param->rxPower >= 1 && param->rxPower <= 4)
        {
            msgStream << WCDMA_MESSAGE_TYPE_BS_SETTING; 
			msgStream << WCDMA_MESSAGE_CODE_BS_SETTING_PILOT;
			msgStream << param->rxPower;

		    send_wcdma_udp_msg(msgStream.str().c_str(),msgStream.str().length());
		}
	}	
}

void handleWcdmaUdpBsConfigPowerResponse(const char* buf, ssize_t len)
{
    std::string msg = "";
	vector<std::string> payload;
	std::string delim = " ";

	msg.assign(buf, len);
	insplit(msg, delim, &payload);

    //add end mark
    payload[1] += "\0";

    WCDMALogNotice("SETPOWER %s", payload[1].c_str());    
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, payload[1].c_str()) == 0)
    {   
	    WCDMALogNotice("Config power success.");  
    }
	else
	{
		WCDMALogError("Config power failure.");  	
	}	
}

void handleWcdmaUdpBsConfigStatusResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    std::string msg = "";
	vector<std::string> payload;
	std::string delim = "#";

	msg.assign(buf, len);

	insplit(msg, delim, &payload);

    //add end mark
    memcpy(ret, payload[1].c_str(), 1);

    if(strcmp(WCDMA_MESSAGE_STATUS_NORMAL, ret) == 0)
    {
	    WCDMALogDebug("NodeB is running.");  
    }
	else
	{
		WCDMALogError("NodeB stopped.");  	
	}

    //set wcdma board time when received the first message
    if(getWcdmaModuleState() == WCDMA_MODULE_IDLE  ||  
	   getWcdmaModuleState() == WCDMA_MODULE_CONFIGING)
    {
        char curr[15];
  	    std::string setTime = "";

        setwcdmadevtimestr(curr);
        setTime += WCDMA_MESSAGE_TYPE_BS_CONFIG;
        setTime += WCDMA_MESSAGE_CODE_BS_CONFIG_TIME;
		setTime.append(curr);
        
		send_wcdma_udp_msg(setTime.c_str(), setTime.length());
		if(getWcdmaModuleState() == WCDMA_MODULE_IDLE)
		{
           setWcdmaModuleState(WCDMA_MODULE_PRECONFIG);
		}
		else
		{
           setWcdmaModuleState(WCDMA_MODULE_CONFIGING);
		}
    }

	if(!wcdmaPaState && wcdmaIsReboot)
	{
		handleWcdmaPaCtrl(true, WCDMA_PA_TYPE_NOTHING);
		wcdmaPaState = true;
		wcdmaIsReboot = false;
		WCDMALogNotice("wcdma recv Bscfg status and open pa \n");
	}
	
	wcdmaHbCounter++;
}

void handleWcdmaUdpBsConfigIpResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;    
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {   
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
	    WCDMALogNotice("NodeB set IP success.");  
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_IP_FAILED);	
		WCDMALogError("NodeB set IP failure.");  	
	}
}

void handleWcdmaUdpBsConfigRestartResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {   
        buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
	    WCDMALogNotice("NodeB restart success.");

		setWcdmaModuleState(WCDMA_MODULE_RESTART);
		wcdmaIsSetTime = true;
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_RESTART_FAILED);	
		WCDMALogError("NodeB restart failure.");
	}
}

void handleWcdmaUdpBsUploadIMSI(const char* buf, ssize_t len)
{
    std::string msg;
	vector<std::string> report;
	std::string delim = "#";

	msg.assign(buf, len);
	insplit(msg, delim, &report);

	RESULT rc = RC_MOD_INVALID;	
	//U64 ctime = getWcdmaCurrentTime();	
	U64 ctime = time(NULL);
	U8 imsi[20] = {0};	
	U8 imei[20] = {0};
	U8 slotId = WCDMA_SLOT; 

    if(!report[0].empty())
    {
       memcpy(imsi, report[0].c_str(), report[0].length());
    }

	if(!report[1].empty())
	{
		memcpy(imei, report[1].c_str(), report[1].length());
	}
	
	//dbgprintf(DEBUG_NOTICE, stdout, "time= %llu  imsi = %s",  ctime, (char *)imsi);
	rc = CM_SendMsg_4Para(MODULE_DATAPRO, MODULE_WCDMA_CAP,MSG_TYPE_INTERNAL, CMD_EVENT, CMD_EVT_EUTRAN_UEID, 0, 
	  					  PARA_TYPE_EUTRAN_TIME, 8, (U8 *)&ctime, 
						  PARA_TYPE_EUTRAN_UEID_IMSI, UE_ID_LENGTH, (U8 *)imsi,
						  PARA_TYPE_EUTRAN_UEID_IMEI, UE_ID_LENGTH, (U8 *)imei, 
						  PARA_TYPE_EUTRAN_BBU_SLOT_ID, 1, (U8 *)&slotId);
    setWcdmaModuleRecvImsi();	
	increaseWcdmaSendCounter(rc);
}

void handleWcdmaConfigTimeResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    WCDMALogNotice("%s", buf);
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {
	     WCDMALogNotice("NodeB set time success.");
		 
         if(getWcdmaModuleState() == WCDMA_MODULE_CONFIGING)
         {
              wcdmaParam_t *pWcdmaParam = &gWcdmaParam;
           	  //for building message
              stringstream msgStream;
              msgStream << WCDMA_MESSAGE_TYPE_BS_CONFIG;
		      msgStream << WCDMA_MESSAGE_CODE_BS_CONFIG_PARAM;
		      
              //build the configuration message to wcdma board
              msgStream << WCDMA_MESSAGE_BODY_MCC << pWcdmaParam->mcc << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_MNC << setw(2) <<setfill('0') << pWcdmaParam->mnc << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_LAC << pWcdmaParam->lac << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_ARFCNo << pWcdmaParam->arfcn << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_PSC << pWcdmaParam->psc << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_RAC << pWcdmaParam->rac << WCDMA_MESSAGE_BODY_AT;
              msgStream << WCDMA_MESSAGE_BODY_CELLID << pWcdmaParam->cellid << WCDMA_MESSAGE_BODY_AT;

              send_wcdma_udp_msg(msgStream.str().c_str(), msgStream.str().length());
         }
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_TIME_FAILED);
		WCDMALogError("NodeB set time failure.");  	
	}
}

void handleWcdmaUdpBsConfig(const char* buf, ssize_t len)
{
   char         msgCode[3] = {0};
   const char   *msgPtr = buf;
   ssize_t      length = len;

   //skip message type
   msgPtr += WCDMA_MESSAGE_TYPE_LENGTH;
   length -= WCDMA_MESSAGE_TYPE_LENGTH;
   
   memcpy(msgCode, msgPtr, WCDMA_MESSAGE_CODE_LENGTH);
   msgPtr += WCDMA_MESSAGE_CODE_LENGTH;
   length -= WCDMA_MESSAGE_CODE_LENGTH;
   
   if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_PARAM_RSP, msgCode) == 0)
   {
	   handleWcdmaUdpBsConfigParamResponse(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_POWER_RSP, msgCode) == 0)
   {
	   handleWcdmaUdpBsConfigPowerResponse(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_STATUS, msgCode) == 0)
   {
	   handleWcdmaUdpBsConfigStatusResponse(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_IP, msgCode) == 0)
   {
	   handleWcdmaUdpBsConfigIpResponse(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_RESTART_RSP, msgCode) == 0)
   {
	   handleWcdmaUdpBsConfigRestartResponse(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_IMSI, msgCode) == 0)
   {
	   handleWcdmaUdpBsUploadIMSI(msgPtr, length);
   }
   else if(strcmp(WCDMA_MESSAGE_CODE_BS_CONFIG_TIME_RSP, msgCode) == 0)
   {
	   handleWcdmaConfigTimeResponse(msgPtr, length);
   }   
   else
   {   
	   WCDMALogError("Unknown msg type: %s", msgCode);	
   }   
}


/**
 ****************************************************************************************
 * Handle setting type message response
 *
 ****************************************************************************************
 */ 
void handleWcdmaUdpBsSettingPilotResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {
        buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);    
	    WCDMALogNotice("Set pilot power success.");  
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_PILOT_FAILED);	
		WCDMALogError("Set pilot power Failure.");  	
	}
}

void handleWcdmaUdpBsSettingAutoLacResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {   
        buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
	    WCDMALogNotice("Set pilot power success.");  
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_AUTOLAC_FAILED);        
		WCDMALogError("Set pilot power Failure.");  	
	}
}

void handleWcdmaUdpBsSettingSwVersionResponse(const char* buf, ssize_t len)
{
	WCDMALogNotice("Software Verion %.", buf);
}

void handleWcdmaUdpBsSettingGetDacResponse(const char* buf, ssize_t len)
{
    int32_t dac = atoi(buf);

	WCDMALogNotice("NodeB DAC is %d.", dac);
}

void handleWcdmaUdpBsSettingSetDacResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {   
	     WCDMALogNotice("NodeB set DAC success.");  
		 buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_DAC_FAILED);	
		WCDMALogError("NodeB set DAC failure.");  	
	}
}

void handleWcdmaUdpBsSetting(const char* buf, ssize_t len)
{
	char		 msgCode[3] = {0};
	const char	 *msgPtr = buf;
	ssize_t 	 length = len;
	
	//skip message type
	msgPtr += WCDMA_MESSAGE_TYPE_LENGTH;
	length -= WCDMA_MESSAGE_TYPE_LENGTH;
	
	memcpy(msgCode, msgPtr, WCDMA_MESSAGE_CODE_LENGTH);
	msgPtr += WCDMA_MESSAGE_CODE_LENGTH;
	length -= WCDMA_MESSAGE_CODE_LENGTH;
	
	if(strcmp(WCDMA_MESSAGE_CODE_BS_SETTING_PILOT_RSP, msgCode) == 0)
	{
		handleWcdmaUdpBsSettingPilotResponse(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_BS_SETTING_AUTO_LAC_RSP, msgCode) == 0)
	{
		handleWcdmaUdpBsSettingAutoLacResponse(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_BS_SETTING_SWVERSION_RSP, msgCode) == 0)
	{
		handleWcdmaUdpBsSettingSwVersionResponse(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_BS_SETTING_GET_DAC_RSP, msgCode) == 0)
	{
		handleWcdmaUdpBsSettingGetDacResponse(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_BS_SETTING_SET_DAC_RSP, msgCode) == 0)
	{
		handleWcdmaUdpBsSettingSetDacResponse(msgPtr, length);
	}
	else
	{	
		WCDMALogError("BS configration Unknown msg code: %s", msgCode);  
	} 
}

/****************************************************************************************/
/* Handle radio output type message response                                            */
/****************************************************************************************/
void handleWcdmaUdpRadioOutputStartResponse(const char* buf, ssize_t len)
{  
    char ret[2] = {0};

    ret[0] = *buf;    
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {
		if (getWcdmaModuleState() != WCDMA_MODULE_RUNNING)
    	{
			setWcdmaModuleState(WCDMA_MODULE_RUNNING); 
			handleWcdmaPaCtrl(true, WCDMA_PA_TYPE_NOTHING);
    	}
    
	    WCDMALogNotice("Radio output start success.");  
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_TXSTART_FAILED);	
		WCDMALogError("Radio output start Failure.");  	
	}
}

void handleWcdmaUdpRadioOutputStopResponse(const char* buf, ssize_t len)
{
    char ret[2] = {0};

    ret[0] = *buf;
    if(strcmp(WCDMA_MESSAGE_RESPONSE_CODE_SUCCESS, ret) == 0)
    {
       setWcdmaModuleState(WCDMA_MODULE_SHUTDOWN);
	   WCDMALogNotice("Radio output stop success.");
	   
	   //alway send success to external
       buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_SUCCESS, 0, 0);
	   setWcdmaModuleState(WCDMA_MODULE_SHUTDOWN);
    }
	else
	{
		buildAndSendTlvCmdSetResponseMsg(CMD_SET, PARA_VALUE_RESULT_FAILED, PARA_TYPE_ERROR_CODE, PARA_VALUE_ERROR_WCDMA_TXSTOP_FAILED);	
		WCDMALogError("Radio output stop Failure.");  		
	}
}

void handleWcdmaUdpBsRadioOutput(const char* buf, ssize_t len)
{
	char		 msgCode[3] = {0};
	const char	 *msgPtr = buf;
	ssize_t 	 length = len;
	
	//skip message type
	msgPtr += WCDMA_MESSAGE_TYPE_LENGTH;
	length -= WCDMA_MESSAGE_TYPE_LENGTH;
	
	memcpy(msgCode, msgPtr, WCDMA_MESSAGE_CODE_LENGTH);
	msgPtr += WCDMA_MESSAGE_CODE_LENGTH;
	length -= WCDMA_MESSAGE_CODE_LENGTH;
	
	if(strcmp(WCDMA_MESSAGE_CODE_RADIO_OUTPUT_START_RSP, msgCode) == 0)
	{
		handleWcdmaUdpRadioOutputStartResponse(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_RADIO_OUTPUT_STOP_RSP, msgCode) == 0)
	{
		handleWcdmaUdpRadioOutputStopResponse(msgPtr, length);
	}
	else
	{	
		WCDMALogError("Unknown msg type: %s", msgCode);  
	} 
}

/**
 ****************************************************************************************
 * Handle parmater type message
 * 1. report
 * 2. response
 ****************************************************************************************
 */ 
void handleWcdmaUdpBsParamReport(const char* buf, ssize_t len)
{
    std::string msg = "";
	vector<std::string> result;
	std::string delim = "#";

	int reject = 0;
	
	msg.assign(buf, len);
	insplit(msg, delim, &result);
	reject = atoi(result[4].c_str());
	
    WCDMALogNotice("NodeB parameter LAC %s, RAC %s, PSC %s, CELLID %s, reject %s.", result[0].c_str(),
		           result[1].c_str(),result[2].c_str(),result[3].c_str(),reject == 0 ? "redirect to WCDMA" : "NAS Reject");	
}

void handleWcdmaUdpBsParamResponse(const char* buf, ssize_t len)
{
    std::string msg = "";
	vector<std::string> result;
	std::string delim = "#";
	wcdmaParam_t param;
	wcdmaParam_t *wParam = &gWcdmaParam;

	msg.assign(buf, len);
	insplit(msg, delim, &result);
	
    WCDMALogNotice("NodeB parameter MCC %s, MNC %s, LAC %s, RAC %s, PSC %s, ARFCN0 %s, CELLID %s.", result[0].c_str(),
		           result[1].c_str(),result[2].c_str(),result[3].c_str(),result[4].c_str(),result[5].c_str(),
		           result[6].c_str());
	
    WCDMALogNotice("NodeB Power %s, pilot %s, auto LAC %s, redirect %s, extern power %s.", result[7].c_str(),
		           result[8].c_str(),result[9].c_str(),result[10].c_str(),result[11].c_str(),result[12].c_str());	

    param.mcc = atoi(result[0].c_str());
    param.mnc = atoi(result[1].c_str());
    param.lac = atoi(result[2].c_str());
    param.rac = atoi(result[3].c_str());
    param.psc = atoi(result[4].c_str());
    param.arfcn = atoi(result[5].c_str());
    param.cellid = atoi(result[6].c_str());
    param.rxPower = wParam->rxPower;
    param.txPower = wParam->txPower;
    param.autolac = wParam->autolac;
    param.dac = wParam->dac;
	
	buildAndReportWcdmaConfiguration(&param);
}

void handleWcdmaUdpBsParam(const char* buf, ssize_t len)
{
	char		 msgCode[3] = {0};
	const char	 *msgPtr = buf;
	ssize_t 	 length = len;
	
	//skip message type
	msgPtr += WCDMA_MESSAGE_TYPE_LENGTH;
	length -= WCDMA_MESSAGE_TYPE_LENGTH;
	
	memcpy(msgCode, msgPtr, WCDMA_MESSAGE_CODE_LENGTH);
	msgPtr += WCDMA_MESSAGE_CODE_LENGTH;
	length -= WCDMA_MESSAGE_CODE_LENGTH;
	
	if(strcmp(WCDMA_MESSAGE_CODE_BS_PARAM_REPORT, msgCode) == 0)
	{
		handleWcdmaUdpBsParamReport(msgPtr, length);
	}
	else if(strcmp(WCDMA_MESSAGE_CODE_BS_PARAM_RESPONSE, msgCode) == 0)
	{
		handleWcdmaUdpBsParamResponse(msgPtr, length);
	}
	else
	{
		WCDMALogError("Unknown msg type: %s", msgCode);  
	} 
}

/*
 * callback func to handle message of a UDP connection.
 */
static void handle_wcdma_udp_message(struct conn_t* c, const char* buf, ssize_t len)
{
    char msgType[3] = {0};
    memcpy(msgType, buf, 2);
	WCDMALogDebug("Message: %s", buf);

	if(strcmp(WCDMA_MESSAGE_TYPE_BS_CONFIG, msgType) == 0)
	{
	    handleWcdmaUdpBsConfig(buf, len);
	}
	else if(strcmp(WCDMA_MESSAGE_TYPE_BS_SETTING, msgType) == 0)
	{
	    handleWcdmaUdpBsSetting(buf, len);
	}
	else if(strcmp(WCDMA_MESSAGE_TYPE_RADIO_OUTPUT, msgType) == 0)
	{
	    handleWcdmaUdpBsRadioOutput(buf, len);
	}
	else if(strcmp(WCDMA_MESSAGE_TYPE_BS_PARAM, msgType) == 0)
	{
	    handleWcdmaUdpBsParam(buf, len);
	}
	else
	{	
	    WCDMALogError("Unknown msg type: %s", msgType);  
	}
}

static void on_close(struct conn_t* c)
{
    /* do nothing */
    release_connection(c);
}

static void on_error(struct conn_t* c)
{
    /* do nothing */
    release_connection(c);
}

static struct conn_cb_t udp_callback = {
       handle_wcdma_udp_message,
       on_close,
       on_error
};

bool init_wcdma_udp_context(sockaddr_in *remote_addr, sockaddr_in* local_addr)
{
    conn_context_init(&wcdma_udp_ctxt);

    /*
     * make a udp connecton to a remote peer 
     */
    wcdma_udp_conn_t = make_udpconn_to(&wcdma_udp_ctxt, remote_addr, &udp_callback);
    
    /*
     * bind local address for receiving msg from remote peer
     */
    bind_local_address(wcdma_udp_conn_t, local_addr);
    
    return true;
}

static void* wcdma_udp_task_thread(void *arg __attribute__((unused)))
{
    WCDMALogNotice("wcdma_udp_task_thread thread id is %lu.", pthread_self()); 
    pthread_setname_np(pthread_self(), "wcdma_udp_task");

     /*
     * start main loop to handle network messasge
     *
     */
    main_loop(&wcdma_udp_ctxt);

    WCDMALogNotice("Exiting the wcdma_udp_task_thread thread.");
    pthread_exit( (void*)0 );
}

bool initWcdmaUdpMsgTask()
{
    pthread_t       thread;
    pthread_attr_t  attr;
    struct sched_param sched;
    int32_t minAllowedPrio, maxAllowedPrio;
    int32_t schedPolicy = SCHED_OTHER;
    int32_t schedPriority = 0;

    if( pthread_attr_init(&attr) )
    {
        WCDMALogError("pthread_attr_init failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) )
    {
        WCDMALogError("pthread_attr_setinheritsched failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) )
    {
        WCDMALogError("pthread_attr_setdetachstate failed: %s.", strerror(errno));
        return false;
    }

    /****************** Setup scheduling **************************/
    /* If we are not superuser, don't try changing scheduling */
    if( (getuid() != 0) && (schedPolicy != SCHED_OTHER) )
    {
        WCDMALogError("Don't have permission for ttisched != OTHER");
        return false;
    }

    if( schedPolicy == SCHED_OTHER && schedPriority != 0 )
    {
        WCDMALogError("maxp %d invalid for ttisched OTHER (must be 0).",schedPriority);
        return false;
    }

    if( (minAllowedPrio = sched_get_priority_min(schedPolicy)) < 0 )
    {
        WCDMALogError(" sched_get_priority_min failed : %s.", strerror(errno));
        return false;
    }

    if( (maxAllowedPrio = sched_get_priority_max(schedPolicy)) < 0)
    {
        WCDMALogError(" sched_get_priority_max failed : %s.", strerror(errno));
        return false;
    }

    if( schedPriority > maxAllowedPrio )
    {
        WCDMALogError(" xp %d greater than max allowed for ttisched, %d.",
                schedPriority, maxAllowedPrio);
        return false;
    }

    if( schedPriority < minAllowedPrio )
    {
        WCDMALogError(" maxp %d lower than min allowed for ttisched, %d.",
                schedPriority, minAllowedPrio);
        return false;
    }

    if( pthread_attr_setschedpolicy(&attr,schedPolicy) )
    {
        WCDMALogError(" pthread_attr_setschedpolicy failed: %s.", strerror(errno));
        return false;
    }

    // Get the scheduling-parameters portion of the attr structure initialized
    // via pthread_attr_init() above
    if( pthread_attr_getschedparam(&attr, &sched) )
    {
        WCDMALogError(" pthread_attr_getschedparam failed : %s.", strerror(errno));
        return false;
    }
    // Update the priority with the value passed in
    sched.sched_priority = schedPriority;
    // Update the priority in the attr structure
    if( pthread_attr_setschedparam(&attr, &sched) )
    {
        WCDMALogError(" pthread_attr_setschedparam failed : %s.", strerror(errno));
        return false;
    }

    if( pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM) )
    {
        WCDMALogError(" pthread_attr_setscope failed : %s.", strerror(errno));
        return false;
    }

    WCDMALogNotice("begin to create wcdma_udp_task_thread.");
    if( pthread_create(&thread, &attr, wcdma_udp_task_thread, 0) )
    {
        WCDMALogError(" pthread_create wcdmaUdptask thread failed: %s.", strerror(errno));
        return false;
    }
    
    return true;
}


